home *** CD-ROM | disk | FTP | other *** search
- /* *****************************************************************************
- FILE: TIFF.c
-
- DESCRIPTION: routine for reading in TIFF files
-
- ***************************************************************************** */
-
-
- #include "TIFF.h"
- /*
- #include "Error.h"
- #include "FileIO.h"
- #include "PhotoAlbumUtils.h"
- #include "AppGlobals.h"
- #include "GrafixUtils.h"
- */
- #include <Script.h>
- #include <Errors.h>
- #include <Memory.h>
- #include <PictUtil.h>
-
- #include "BitMapUtils.h"
-
-
- TIFF_RecHdl TIFF_Rec_Hdl;
- GWorldPtr display_image_GW;
- WindowPtr display_window;
-
-
- static OSErr CopyToGWorld ( GWorldPtr gw );
-
-
- /************************************************************************
- ************************************************************************/
-
- GWorldPtr ReadTIFF( FSSpec *spec, short forImage, OSErr *theError, Rect *bounds )
- {
- GDHandle saveDevice;
- GDHandle mainDevice;
- CGrafPtr savePort;
- GWorldPtr myGW, thumb_gw;
- HParamBlockRec openParams;
- Rect newRect, tempRect;
- GWorldFlags myGWorldFlags;
- OSErr theErr;
- FSSpec localSpec;
- short vRefNum, refNum, bit_depth;
- Boolean OK;
- Str255 temp_str = "\p";
- PixMapHandle pm;
-
-
- localSpec = *spec;
- vRefNum = localSpec.vRefNum;
-
- /* Set up for the file that we want to use. */
- openParams.fileParam.ioCompletion = NULL;
- openParams.fileParam.ioNamePtr = localSpec.name;
- openParams.fileParam.ioVRefNum = vRefNum;
- openParams.ioParam.ioVersNum = 0;
- openParams.ioParam.ioPermssn = fsRdPerm;
- openParams.ioParam.ioMisc = NULL;
- openParams.fileParam.ioDirID = localSpec.parID;
-
- theErr = PBHOpenDF( &openParams, FALSE );
-
- if ( ( theErr == fnfErr ) || ( theErr == nsvErr ) )
- {
- *theError = theErr;
- return ( ( GWorldPtr ) NULL );
- }
-
- refNum = openParams.ioParam.ioRefNum;
-
- TIFF_Rec_Hdl = ( TIFF_RecHdl ) NewHandle( ( long ) sizeof( **TIFF_Rec_Hdl ) );
-
- theErr = MemError( );
- OK = (theErr == noErr); // TO DO: may need an alert here if an error
-
- if ( !OK )
- {
- FSClose( refNum );
- *theError = theErr;
- return ( ( GWorldPtr ) NULL );
- }
-
- ( *TIFF_Rec_Hdl )->ref = -1;
- ( *TIFF_Rec_Hdl )->ti = 0;
- ( *TIFF_Rec_Hdl )->depth = 32;
- ( *TIFF_Rec_Hdl )->dither = FALSE;
- ( *TIFF_Rec_Hdl )->customPalette = TRUE;
- ( *TIFF_Rec_Hdl )->customMethod = systemMethod;
-
- ( *TIFF_Rec_Hdl )->ref = refNum;
-
- ( *TIFF_Rec_Hdl )->ti = ScanTIFF( ( *TIFF_Rec_Hdl )->ref );
-
- if ( ( *TIFF_Rec_Hdl )->ti == 0 || GetTIFFError( ( *TIFF_Rec_Hdl )->ti, temp_str ) != 0 )
- {
- SysBeep(1); // TO DO: Alert if Error
- DisposeThunk( TIFF_Rec_Hdl );
- return ( ( GWorldPtr ) NULL );
- }
-
- if ( TIFFDrawable( ( *TIFF_Rec_Hdl )->ti ) == FALSE )
- {
- DisposeThunk( TIFF_Rec_Hdl );
- return ( ( GWorldPtr ) NULL );
- }
-
- // eliminate excess depth
- if ( ( *TIFF_Rec_Hdl )->ti->samplesPerPixel == 1 && ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0] < ( *TIFF_Rec_Hdl )->depth )
- {
- ( *TIFF_Rec_Hdl )->depth = FixDepth( ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0] );
- }
-
- newRect.left = 0;
- newRect.top = 0;
- newRect.right = ( *TIFF_Rec_Hdl )->ti->imageWidth;
- newRect.bottom = ( *TIFF_Rec_Hdl )->ti->imageLength;
-
- GetGWorld( &savePort, &saveDevice );
-
-
- theErr = MakeSafeGWorld( &myGW, &newRect, ( *TIFF_Rec_Hdl )->depth, ( *TIFF_Rec_Hdl )->ti->colorMap, TRUE );
-
- SetGWorld( savePort, saveDevice );
-
- if ( theErr == noErr )
- {
- if ( ( theErr = CopyToGWorld( myGW ) ) != noErr )
- {
- if ( GetTIFFError( ( *TIFF_Rec_Hdl )->ti, temp_str ) != 0 && temp_str[0] != 0 )
- {
- SysBeep(1); // TO DO: Error Alert
- DisposeThunk( TIFF_Rec_Hdl );
- DisposeGWorld( myGW );
- *theError = theErr;
- return ( ( GWorldPtr ) NULL );
- }
- }
-
- FSClose( ( *TIFF_Rec_Hdl )->ref );
- ( *TIFF_Rec_Hdl )->ref = -1;
- }
-
- *bounds = newRect;
-
- if ( forImage == FALSE )
- {
- bit_depth = ( *TIFF_Rec_Hdl )->ti->samplesPerPixel * ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0];
-
- if ( myGW == NULL )
- {
- GetGWorld( &savePort, &saveDevice );
- theErr = MakeSafeGWorld( &myGW, &newRect, 8, ( CTabHandle ) NULL, TRUE );
- SetGWorld( savePort, saveDevice );
-
- theErr = CopyToGWorld( myGW );
- }
-
- newRect = myGW->portRect;
- CalculateThumbNailSize( newRect.right, newRect.bottom, &newRect );
-
- GetGWorld( &savePort, &saveDevice );
-
- theErr = MakeSafeGWorld( &thumb_gw, &newRect, bit_depth, ( CTabHandle ) NULL, TRUE );
-
-
- SetGWorld( savePort, saveDevice );
-
- if ( theErr == noErr )
- {
- LockPixels( myGW->portPixMap );
- LockPixels( thumb_gw->portPixMap );
-
- GetGWorld( &savePort, &saveDevice );
- SetGWorld( thumb_gw, NULL );
-
- EraseRect( &( thumb_gw->portRect ) );
- CopyBits( ( BitMap * ) &myGW->portPixMap, ( BitMap * ) &thumb_gw->portPixMap,
- &myGW->portRect, &newRect, ditherCopy, NULL );
-
- SetGWorld( savePort, saveDevice );
-
- UnlockPixels( myGW->portPixMap );
- UnlockPixels( thumb_gw->portPixMap );
-
- DisposeGWorld( myGW );
- myGW = NULL;
- }
-
- DisposeThunk( TIFF_Rec_Hdl );
- *theError = theErr;
- return ( thumb_gw );
- }
- else
- {
- DisposeThunk( TIFF_Rec_Hdl );
- *theError = noErr;
- return ( myGW );
- }
- }
-
-
- /************************************************************************
- ************************************************************************/
-
- static OSErr CopyToGWorld( GWorldPtr gw )
- {
- CGrafPtr oldPort;
- GDHandle oldGD;
- PixMapHandle pm;
- OSErr err;
- Rect r;
-
-
- GetGWorld( &oldPort, &oldGD );
- SetGWorld( gw, NULL );
-
- pm = GetGWorldPixMap( gw );
-
- if ( LockPixels( pm ) != TRUE )
- {
- SetGWorld( oldPort, oldGD );
- return ( memFullErr );
- }
-
- r = gw->portRect;
- err = DrawTIFF( ( *TIFF_Rec_Hdl )->ref, ( *TIFF_Rec_Hdl )->ti, r, r, ( *TIFF_Rec_Hdl )->dither );
-
- UnlockPixels( pm );
- SetGWorld( oldPort, oldGD );
-
- return ( err );
- }
-
-
- /************************************************************************
- ************************************************************************/
-
- void DisposeThunk( TIFF_RecHdl th )
- {
- if ( th )
- {
- if ( ( *th )->ti )
- {
- DisposeTIFF( ( *th )->ti );
- }
-
- if ( ( *th )->ref != -1 )
- {
- FSClose( ( *th )->ref );
- }
-
- if ( display_image_GW )
- {
- DisposeGWorld( display_image_GW );
- display_image_GW = NULL;
- }
-
- DisposHandle( ( Handle ) th );
- th = NULL;
- }
- }
-
-
-
- /************************************************************************
- ************************************************************************/
-
- // •••
- // Give the window an appropriate palette. Such a palette should have a separate
- // set of colors for each different depth CLUT device the window intersects.
- // This is possible using inhibited entries, but would be expensive since it
- // would require multiple calls to GetPixMapInfo(). And the palette might have
- // to be recomputed whenever the user moves the window onto a different screen
- // or changes the depth with the Monitors control panel.
- //
- // It would be nice if the color sampling methods used by GetPixMapInfo() returned
- // a palette with the most important colors first, or with multiple sets of
- // inhibited colors; such a palette would be useful at multiple depths.
- //
- // This routine computes a palette for the deepest CLUT device existing at the
- // time the TIFF window was created. This isn't perfect; the user might put
- // the window on a shallower screen, or change the depth.
- //
- // InitPalette the color map in the TIFF file if it can. Otherwise it uses the
- // Picture Utilities. The sampling method cpmt resource number can be set with
- // the 5th argument to TIFFWindow.
- // •••
-
- void InitPalette( )
- {
- CTabHandle cth;
- PaletteHandle pltt = 0, opltt;
- PictInfo pi;
- PixMapHandle pm;
- OSErr err;
- short deepest, size;
-
-
- if ( display_image_GW != NULL )
- {
- return;
- }
-
- deepest = DeepestCLUTScreen( );
- size = DepthToSize( deepest );
-
- // Don't bother if there are no color CLUT screens.
- if ( deepest <= 1 )
- {
- return;
- }
-
- if ( ( cth = ( *TIFF_Rec_Hdl )->ti->colorMap ) && ( ( *cth )->ctSize + 1 ) <= size )
- {
- // Use the color map in the TIFF file if it isn't too large.
- pltt = NewPalette( ( *cth )->ctSize + 1, cth, pmTolerant, 0 );
- }
- else
- if ( ( ( *TIFF_Rec_Hdl)->ti->samplesPerPixel > 1 || ( *TIFF_Rec_Hdl )->ti->bitsPerSample[0] > 1) && ( *TIFF_Rec_Hdl )->customPalette && display_image_GW )
- {
- pm = GetGWorldPixMap( display_image_GW );
-
- if ( LockPixels( pm ) == TRUE )
- {
- err = GetPixMapInfo( pm, &pi, returnPalette | suppressBlackAndWhite, size - 2, ( *TIFF_Rec_Hdl )->customMethod, 0 );
-
- if ( err == noErr )
- {
- pltt = pi.thePalette;
- pi.thePalette = 0;
- }
-
- UnlockPixels( pm );
- }
- }
-
- if ( pltt )
- {
- SetPalette( display_window, pltt, TRUE );
- }
- }
-
-
- /************************************************************************
- ************************************************************************/
-
- // •••
- // Return the depth of the deepest CLUT screen, or zero if there are no
- // CLUT screens.
- // •••
- short DeepestCLUTScreen( )
- {
- GDHandle gd;
- short depth = 0;
- PixMapHandle pm;
-
-
- gd = GetDeviceList( );
-
- while ( gd )
- {
- if ( TestDeviceAttribute( gd, screenDevice ) == TRUE && TestDeviceAttribute( gd, screenActive ) == TRUE && ( *gd )->gdType == 0 )
- {
- pm = ( *gd )->gdPMap;
-
- if ( pm && ( *pm )->cmpCount == 1 && ( *pm )->cmpSize > depth )
- {
- depth = ( *pm )->cmpSize;
- }
- }
-
- gd = GetNextDevice( gd );
- }
-
- return ( depth );
- }
-
-
- /************************************************************************
- ************************************************************************/
-
- short DepthToSize( short depth )
- {
- switch ( depth )
- {
- case 1:
- return ( 2 );
- break;
-
- case 2:
- return ( 4 );
- break;
-
- case 4:
- return ( 16 );
- break;
-
- default:
- return ( 256 );
- }
- }
-
-
- /************************************************************************
- ************************************************************************/
-
- // •••
- // Take whatever depth the user provided and round it up to the nearest
- // legal QuickDraw depth.
- // •••
- short FixDepth( short depth )
- {
- if ( depth < 1 )
- {
- return ( 0 );
- }
-
- if ( depth <= 1 )
- {
- return ( 1 );
- }
-
- if ( depth <= 2 )
- {
- return ( 2 );
- }
-
- if ( depth <= 4 )
- {
- return ( 4 );
- }
-
- if ( depth <= 8 )
- {
- return ( 8 );
- }
-
- if ( depth <= 16 )
- {
- return ( 16 );
- }
-
- return ( 32 );
- }
-
-
-
-
-
- /************************************************************************
- ************************************************************************/
-
- double CalculateThumbNailSize( double old_wide, double old_high, Rect *new_size )
- {
- short new_wide, new_high;
- double ratio;
-
-
- if ( old_wide > old_high )
- {
- ratio = old_wide / THUMB_SIZE;
- new_wide = THUMB_SIZE;
- new_high = old_high / ratio;
- }
- else
- if ( old_high > old_wide )
- {
- ratio = old_high / THUMB_SIZE;
- new_high = THUMB_SIZE;
- new_wide = old_wide / ratio;
- }
- else
- if ( old_wide < THUMB_SIZE )
- {
- new_high = old_high;
- new_wide = old_wide;
- }
- else
- if ( old_high < THUMB_SIZE )
- {
- new_high = old_high;
- new_wide = old_wide;
- }
- else
- {
- new_high = THUMB_SIZE;
- new_wide = THUMB_SIZE;
- }
-
- SetRect( new_size, 0, 0, new_wide, new_high );
-
- return ( ratio );
- }
-
-
- //*********************************************************************************
-
- // This code added to support create preview in file dialog
-
- OSErr ConvertTIFFToPICT(FSSpec *theFile,PicHandle *thePicture)
- {
- OSErr theErr;
- GWorldPtr tiffWorld;
- Rect bounds;
- PicHandle temp;
- CGrafPtr savePort;
- GDHandle saveDevice;
- PixMapHandle tiffPix;
-
- tiffWorld = ReadTIFF(theFile,TRUE,&theErr,&bounds);
-
- if ((theErr == noErr) && tiffWorld)
- {
- bounds = tiffWorld->portRect;
- GetGWorld(&savePort,&saveDevice);
- SetGWorld(tiffWorld,NULL);
-
- tiffPix = GetGWorldPixMap(tiffWorld);
-
- if (LockPixels(tiffPix))
- {
- temp = OpenPicture(&bounds);
- ClipRect(&bounds);
- CopyBits((BitMap*)*tiffPix,(BitMap*)*tiffPix,&bounds,&bounds,srcCopy,NULL);
- UnlockPixels(tiffPix);
- ClosePicture();
- }
-
- SetGWorld(savePort,saveDevice);
- DisposeGWorld(tiffWorld);
-
- *thePicture = temp;
- }
- return(theErr);
- }